package Common.Managers 
{
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.system.ApplicationDomain;
	import flash.utils.Dictionary;
	import flash.events.IOErrorEvent;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import Game.Windows.DebugWindow;

	/**
	 * ...
	 * @author Yevgeniy Logachev
	 */
	public class SwfManager
	{
		private static var m_swfList:Dictionary = new Dictionary();
		private static const s_instance:SwfManager = new SwfManager();
		
		public function SwfManager() 
		{
			if (s_instance == null)
			{
				trace ("Swf Manager initialized");
			}
			else
			{
				trace("ERROR: Already existing instance in Singleton");
				throw new Error("Already existing instance in Singleton");
			}
		}
		
		public static function get instance():SwfManager
		{
			return s_instance;
		}
		
		public function load(swfUrl:String, funcHandler:Function):void
		{
			if (isLoaded(swfUrl))
			{
				funcHandler();
			}
			else
			{
				var entity:SwfEntity = new SwfEntity(swfUrl);
				entity.addEventListener(Event.COMPLETE, onLoad);
				entity.m_funcHandler = funcHandler;
				m_swfList[swfUrl] = entity;
			}
			
			function onLoad(e:Event):void
			{	
				entity.removeEventListener(Event.COMPLETE, onLoad);
				
				(m_swfList[swfUrl] as SwfEntity).m_funcHandler();
			}	
		}
		
		public function loadAll(swfUrls:Array, funcHandler:Function):void
		{
			for (var i:int = 0; i < swfUrls.length; ++i)
			{
				load(swfUrls[i], checkIsAllLoaded);
			}
			
			function checkIsAllLoaded():void
			{
				if (isAllLoaded(swfUrls))
				{
					funcHandler();
				}
			}
		}
		
		public function remove(swfUrl:String)	:void
		{
			(m_swfList[swfUrl] as SwfEntity).release();
			delete m_swfList[swfUrl];
		}
		
		public function releaseAll():void
		{
			for each(var entity:SwfEntity in m_swfList)
			{
				entity.release();
			}
			m_swfList = new Dictionary();
		}
		
		public function getSWF(swfUrl:String, symbol:String):Class
		{
			if(m_swfList[swfUrl] == undefined) return null;
			
			if ((m_swfList[swfUrl] as SwfEntity).m_loaded)
			{
				var appDom:ApplicationDomain = (m_swfList[swfUrl] as SwfEntity).m_loader.contentLoaderInfo.applicationDomain;
				
				if(appDom.hasDefinition(symbol))
				{
					return appDom.getDefinition(symbol) as Class;
				}
			}
			return null;
		}
		
		public function getSprite(swfUrl:String, symbol:String):Sprite
		{
			if(isLoaded(swfUrl))
			{
				var swfClass:Class = getSWF(swfUrl, symbol);
				return new swfClass();
			}
			
			var sprite:Sprite = new Sprite();
			
			load(swfUrl, onLoad);
			function onLoad(e:Event):void
			{
				var swfClass:Class = getSWF(swfUrl, symbol);
				sprite.addChild(new swfClass);
			}
			
			return sprite;
		}
		
		public function isLoaded(swfUrl:String):Boolean
		{
			if (m_swfList[swfUrl] == undefined) return false;

			return (m_swfList[swfUrl] as SwfEntity).m_loaded;
		}
		
		public function isAllLoaded(swfUrls:Array):Boolean
		{
			var done:Boolean = true;
			DebugWindow.instance.addLine("*************************");
			for (var i:int = 0; i < swfUrls.length; ++i)
			{
				done &&= isLoaded(swfUrls[i]);
				
				DebugWindow.instance.addLine(swfUrls[i] + " : " + isLoaded(swfUrls[i]));
			}
			return done;
		}
	}
}
import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
import flash.system.LoaderContext;

// ======================== Additional class =========================
class SwfEntity extends EventDispatcher
{
	public var m_swfUrl:String;

	// holds the asset
	public var m_loader:Loader = null;
	public var m_loaded:Boolean = false;
	public var m_funcHandler:Function;

	public function SwfEntity(swfUrl:String)
	{
		m_swfUrl = swfUrl;
		
		var loadingContext:LoaderContext = new LoaderContext;
		loadingContext.checkPolicyFile = true;
		
		m_loader = new Loader();
		m_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoad, false, 0, true);
		m_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError);
		m_loader.load(new URLRequest(swfUrl), loadingContext);
	}
	
	private function onError(e:Event):void
	{
		m_loaded = false;
	}
	
	private function onLoad(e:Event):void
	{
		m_loaded = true;
		m_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoad);
		
		dispatchEvent(new Event(Event.COMPLETE));
	}
	
	public function release():void
	{
		m_loader = null;
	}
}